package com.lvhr.rpc.fault.tolerant;


import com.lvhr.rpc.model.RpcRequest;
import com.lvhr.rpc.model.RpcResponse;
import com.lvhr.rpc.model.ServiceMetaInfo;
import com.lvhr.rpc.server.tcp.VertxTcpClient;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.Map;

/**
 * 故障转移策略 - 自动切换到其他节点重试
 */
@Slf4j
public class FailOverTolerantStrategy implements TolerantStrategy {

    @Override
    public RpcResponse doTolerant(Map<String, Object> context, Exception e) throws Exception {
        // 1. 从上下文中获取服务节点信息
        List<ServiceMetaInfo> serviceMetaInfos = (List<ServiceMetaInfo>) context.get("serviceMetaInfoList");
        ServiceMetaInfo selectedServiceMetaInfo = (ServiceMetaInfo) context.get("selectedServiceMetaInfo");
        RpcRequest rpcRequest = (RpcRequest) context.get("rpcRequest");

        if (serviceMetaInfos == null || serviceMetaInfos.isEmpty()) {
            throw new RuntimeException("No available service instances for failover");
        }

        // 2. 选择下一个可用节点（排除已失败的节点）
        ServiceMetaInfo newSelected = selectNewService(serviceMetaInfos, selectedServiceMetaInfo);

        if (newSelected == null) {
            throw new RuntimeException("No available service instances after excluding failed one");
        }

        log.info("Failover容错机制启动......当前节点为service node: {}", newSelected);

        // 3. 重新发起调用
        return VertxTcpClient.doRequest(rpcRequest, newSelected);

    }

    /**
     * 选择新的服务节点（简单实现：轮询选择下一个节点）
     */
    private ServiceMetaInfo selectNewService(List<ServiceMetaInfo> serviceMetaInfos,
                                             ServiceMetaInfo excluded) {
        for (ServiceMetaInfo serviceMetaInfo : serviceMetaInfos) {
            if (!serviceMetaInfo.equals(excluded)) {
                return serviceMetaInfo;
            }
        }
        return null;
    }
}
